home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / Xconq 7.0d16 / Xconq 7.0d16 src / mac / macmenus.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-20  |  50.3 KB  |  2,275 lines  |  [TEXT/KAHL]

  1. /* Copyright (c) 1992, 1993  Stanley T. Shebs. */
  2. /* This program may be used, copied, modified, and redistributed freely */
  3. /* for noncommercial purposes, so long as this notice remains intact. */
  4.  
  5. /* Mac menu handling. */
  6.  
  7. #include "conq.h"
  8. #include "mac.h"
  9.  
  10. #undef DEF_CMD
  11. #define DEF_CMD(letter,oldletter,name,args,FN,help) int FN();
  12.  
  13. #include "cmd.def"
  14.  
  15. /* The following is generic code. */
  16.  
  17. int constructioneverpossible = -1;
  18.  
  19. construction_ever_possible()
  20. {
  21.     int u, u2;
  22.  
  23.     if (constructioneverpossible < 0) {
  24.         constructioneverpossible = FALSE;
  25.         for_all_unit_types(u) {
  26.             for_all_unit_types(u2) {
  27.                 if (uu_acp_to_create(u, u2) > 0) {
  28.                     constructioneverpossible = TRUE;
  29.                     return constructioneverpossible;
  30.                 }
  31.             }
  32.         }
  33.     }
  34.     return constructioneverpossible;
  35. }
  36.  
  37. extern Feature *featurelist;
  38.  
  39. extern int gameinited, beforestart, endofgame;
  40.  
  41. #include <profile.h>
  42.  
  43. int Profile = FALSE;
  44.  
  45. #define SetMenuItemText SetItem
  46. #define InsertMenuItem InsMenuItem
  47.  
  48. #define side_may_select(unit) (in_play(unit) && ((unit)->side == dside || dside->designer))
  49.  
  50. #define valid_selection(unit) (in_play(unit) && ((unit)->side == dside || dside->designer))
  51.  
  52. #define menus_tweakable() ((!beforestart && !endofgame) || (gameinited && dside->designer))
  53.  
  54. #define MAXWINDOWS 100
  55.  
  56. extern int gamestatesafe;
  57. extern int interfacestatesafe;
  58.  
  59. char *cursavename = NULL;
  60.  
  61. MenuHandle mapviewmenu = nil;
  62. MenuHandle listviewmenu = nil;
  63. MenuHandle closeupviewmenu = nil;
  64.  
  65. MenuHandle utypemenu = nil;
  66. MenuHandle ttypemenu = nil;
  67. MenuHandle mtypemenu = nil;
  68. MenuHandle sidemenu = nil;
  69. MenuHandle aitypemenu = nil;
  70.  
  71. MenuHandle featuremenu = nil;
  72.  
  73. WindowPtr *winmenuwins;
  74.  
  75. int numwindows;
  76.  
  77. Map *worldmap = NULL;
  78.  
  79. WindowPtr worldmapwin = nil;
  80.  
  81. /* Set up all the menus, at least in their basic form. */
  82.  
  83. init_menus()
  84. {
  85.     int i;
  86.     Handle menubar;
  87.     MenuHandle menu;
  88.  
  89.     menubar = GetNewMBar(mbMain);
  90.     SetMenuBar(menubar);
  91.     /* Add the DAs etc as usual. */
  92.     if ((menu = GetMHandle(mApple)) != nil) {
  93.         AddResMenu(menu, 'DRVR');
  94.     }
  95.     /* Get the different versions of the view menu. */
  96.     mapviewmenu = GetMenu(mViewMap);
  97.     listviewmenu = GetMenu(mViewList);
  98.     closeupviewmenu = GetMenu(mViewCloseup);
  99.     /* Init submenus and popups. */
  100.     if ((menu       = GetMenu(mViewFontSizes)) != nil)  InsertMenu(menu, -1);
  101.     if ((menu       = GetMenu(mMagnifications)) != nil) InsertMenu(menu, -1);
  102.     if ((menu       = GetMenu(mViewWeather)) != nil)    InsertMenu(menu, -1);
  103.     if ((sidemenu   = GetMenu(mSides)) != nil)          InsertMenu(sidemenu, -1);
  104.     if ((utypemenu  = GetMenu(mUnitTypes)) != nil)      InsertMenu(utypemenu, -1);
  105.     if ((mtypemenu  = GetMenu(mMaterialTypes)) != nil)  InsertMenu(mtypemenu, -1);
  106.     if ((ttypemenu  = GetMenu(mTerrainTypes)) != nil)   InsertMenu(ttypemenu, -1);
  107.     if ((aitypemenu = GetMenu(mAITypes)) != nil)        InsertMenu(aitypemenu, -1);
  108.     if ((featuremenu = GetMenu(mFeatures)) != nil)      InsertMenu(featuremenu, -1);
  109.     /* Init the support for the Windows menu. */
  110.     winmenuwins = (WindowPtr *) xmalloc(MAXWINDOWS * sizeof(WindowPtr));
  111.     for (i = 0; i < MAXWINDOWS; ++i) {
  112.         winmenuwins[i] = nil;
  113.     }
  114.     numwindows = 0;
  115.     /* Done fiddling with menus, draw them. */
  116.     DrawMenuBar();
  117. }
  118.  
  119. /* Add a menu item that can be used to go to the given window.  Set the window title
  120.    here too, ensures that the two match. */
  121.  
  122. add_window_menu_item(name, win)
  123. char *name;
  124. WindowPtr win;
  125. {
  126.     int i;
  127.     MenuHandle menu;
  128.     Str255 tmpstr;
  129.  
  130.     if (numwindows < MAXWINDOWS) {
  131.         c2p(name, tmpstr);
  132.         SetWTitle(win, tmpstr);
  133.         winmenuwins[numwindows++] = win;
  134.         if ((menu = GetMHandle(mWindows)) != nil) {
  135.             AppendMenu(menu, tmpstr);
  136.         }
  137.     }
  138. }
  139.  
  140. /* Remove the menu item that can be used to select a given window. */
  141.  
  142. remove_window_menu_item(win)
  143. WindowPtr win;
  144. {
  145.     int i, found = FALSE, next = 0;
  146.     Str255 tmpstr;
  147.     MenuHandle menu;
  148.  
  149.     /* Search for the window and remove it from the array of windows
  150.        that have menu items. */
  151.     for (i = 0; i < numwindows; ++i) {
  152.         if (!found && winmenuwins[i] == win) {
  153.             found = TRUE;
  154.         }
  155.         if (found && i < numwindows - 1) {
  156.             /* Shift the other windows down. */
  157.             winmenuwins[i] = winmenuwins[i + 1];
  158.         }
  159.     }
  160.     /* This routine gets called for all windows, so get out of here
  161.        if this window is not one of those in the menu. */
  162.     if (!found) return;
  163.     --numwindows;
  164.     /* Trash the existing window menu. */
  165.     if ((menu = GetMHandle(mWindows)) != nil) {
  166.         DeleteMenu(mWindows);
  167.         ReleaseResource(menu);
  168.     }
  169.     /* Build a new version starting with the resource. */
  170.     if ((menu = GetMenu(mWindows)) != nil) {
  171.         for (i = 0; i < numwindows; ++i) {
  172.             GetWTitle(winmenuwins[i], tmpstr);
  173.             AppendMenu(menu, tmpstr);
  174.         }
  175.         if (GetMHandle(mViewMap) != nil) next = mViewMap;
  176.         if (GetMHandle(mViewList) != nil) next = mViewList;
  177.         InsertMenu(menu, next);
  178.     }
  179.     DrawMenuBar();
  180. }
  181.  
  182. /* Fill up the side menu. */
  183.  
  184. build_side_menu()
  185. {
  186.     Side *side2;
  187.     Str255 tmpstr;
  188.  
  189.     if (sidemenu != nil && CountMItems(sidemenu) < 1) {
  190.         for_all_sides(side2) {
  191.             shortest_side_title(side2, spbuf);
  192.             sanitize_for_menu(spbuf);
  193.             c2p(spbuf, tmpstr);
  194.             AppendMenu(sidemenu, tmpstr);
  195.             EnableItem(sidemenu, side_number(side2));
  196.         }
  197.         if (1 /* independent units possible in this game */) {
  198.             AppendMenu(sidemenu, "\pindependent");
  199.         }
  200.     }
  201. }
  202.  
  203. update_side_menu(side2)
  204. Side *side2;
  205. {
  206.     Str255 tmpstr;
  207.  
  208.     shortest_side_title(side2, spbuf);
  209.     sanitize_for_menu(spbuf);
  210.     c2p(spbuf, tmpstr);
  211.     SetMenuItemText(sidemenu, side_number(side2), tmpstr);
  212. }
  213.  
  214. build_unit_type_menu()
  215. {
  216.     int u;
  217.     Str255 tmpstr;
  218.  
  219.     if (utypemenu != nil && CountMItems(utypemenu) < 1) {
  220.         for_all_unit_types(u) {
  221.             strcpy(spbuf, u_type_name(u));
  222.             sanitize_for_menu(spbuf);
  223.             c2p(spbuf, tmpstr);
  224.             AppendMenu(utypemenu, tmpstr);
  225.             EnableItem(utypemenu, u + 1);
  226.         }
  227.     }
  228. }
  229.  
  230. build_material_type_menu()
  231. {
  232.     int m;
  233.     Str255 tmpstr;
  234.  
  235.     if (mtypemenu != nil && CountMItems(mtypemenu) < 1 && nummtypes > 0) {
  236.         for_all_material_types(m) {
  237.             strcpy(spbuf, m_type_name(m));
  238.             sanitize_for_menu(spbuf);
  239.             c2p(spbuf, tmpstr);
  240.             AppendMenu(mtypemenu, tmpstr);
  241.             EnableItem(mtypemenu, m + 1);
  242.         }
  243.     }
  244. }
  245.  
  246. build_terrain_type_menu()
  247. {
  248.     int t;
  249.     Str255 tmpstr;
  250.  
  251.     if (ttypemenu != nil && CountMItems(ttypemenu) < 1) {
  252.         for_all_terrain_types(t) {
  253.             strcpy(spbuf, t_type_name(t));
  254.             sanitize_for_menu(spbuf);
  255.             c2p(spbuf, tmpstr);
  256.             AppendMenu(ttypemenu, tmpstr);
  257.             EnableItem(ttypemenu, t);
  258.         }
  259.     }
  260. }
  261.  
  262. build_ai_type_menu()
  263. {
  264.     if (aitypemenu != nil && CountMItems(aitypemenu) < 1) {
  265.         AppendMenu(aitypemenu, "\pNone");
  266.         EnableItem(aitypemenu, 1);
  267.         AppendMenu(aitypemenu, "\pMplayer");
  268.         EnableItem(aitypemenu, 2);
  269.     }
  270. }
  271.  
  272. build_feature_menu()
  273. {
  274.     int i = 1;
  275.     Str255 tmpstr;
  276.     Feature *feature;
  277.  
  278.     if (featuremenu != nil && CountMItems(featuremenu) < 1) {
  279.         AppendMenu(featuremenu, "\pNo Feature");
  280.         EnableItem(featuremenu, i++);
  281.         for (feature = featurelist; feature != NULL; feature = feature->next) {
  282.             feature_desc(feature, spbuf);
  283.             sanitize_for_menu(spbuf);
  284.             c2p(spbuf, tmpstr);
  285.             AppendMenu(featuremenu, tmpstr);
  286.             EnableItem(featuremenu, i++);
  287.         }
  288.     }
  289. }
  290.  
  291. /* Alter the feature menu to reflect a changed or new feature. */
  292.  
  293. update_feature_menu(feature)
  294. Feature *feature;
  295. {
  296.     Str255 tmpstr;
  297.  
  298.     feature_desc(feature, spbuf);
  299.     sanitize_for_menu(spbuf);
  300.     c2p(spbuf, tmpstr);
  301.     if (feature->id + 1 > CountMItems(featuremenu)) {
  302.         AppendMenu(featuremenu, tmpstr);
  303.         EnableItem(featuremenu, feature->id + 1);
  304.     } else {
  305.         SetMenuItemText(featuremenu, feature->id + 1, tmpstr);
  306.     }
  307. }
  308.  
  309. /* This removes chars that are specially recognized by the Menu Manager.
  310.    Has to be done so that strange game-defined names don't scramble the
  311.    menus; innocuous because this affects only the appearance in the menu. */
  312.  
  313. sanitize_for_menu(buf)
  314. char *buf;
  315. {
  316.     int i;
  317.  
  318.     /* Replace a leading hyphen with an underscore. */
  319.     if (buf[0] == '-') buf[0] = '_';
  320.     /* Replace special chars with blanks. */
  321.     for (i = 0; buf[i] != '\0'; ++i) {
  322.         switch (buf[i]) {
  323.             case ';':
  324.             case '!':
  325.             case '<':
  326.             case '/':
  327.             case '(':
  328.             /* I don't think closing parens are special, but since the
  329.                (presumed) matching open paren is gone, might as well get
  330.                rid of the close also. */
  331.             case ')':
  332.                 buf[i] = ' ';
  333.                 break;
  334.             default:
  335.                 break;
  336.         }
  337.     }
  338. }
  339.  
  340. /* Decipher and do a menu command. */
  341.  
  342. do_menu_command(which)
  343. long which;
  344. {
  345.     short menuid, menuitem, itemHit, daRefNum, ditem, i;
  346.     Str255 daname;
  347.     Boolean handledbyda;
  348.     WindowPtr win;
  349.  
  350.     menuid = HiWord(which);
  351.     menuitem = LoWord(which);
  352.     DGprintf("menu %d, item %d\n", menuid, menuitem);
  353.     switch (menuid) {
  354.         case mApple:
  355.             switch (menuitem) {
  356.                 case miAppleAbout:
  357.                     do_about_box();
  358.                     break;
  359.                 case miAppleHelp:
  360.                     help_dialog();
  361.                     break;
  362.                 default:
  363.                     GetItem(GetMHandle(mApple), menuitem, daname);
  364.                     daRefNum = OpenDeskAcc(daname);
  365.             }
  366.             break;
  367.         case mFile:
  368.             switch (menuitem) {
  369.                 case miFileNew:
  370.                     /* (should reset state of everything first) */
  371.                     new_game_dialog();
  372.                     break;
  373.                 case miFileOpen:
  374.                     /* (should reset state of everything first) */
  375.                     open_game_dialog();
  376.                     break;
  377.                 case miFileConnect:
  378.                     connect_game_dialog();
  379.                     break;
  380.                 case miFileSave:
  381.                     save_the_game(FALSE, FALSE);
  382.                     break;
  383.                 case miFileSaveAs:    
  384.                     save_the_game(TRUE, FALSE);
  385.                     break;
  386.                 case miFilePreferences:
  387.                     set_preferences();
  388.                     break;
  389.                 case miFilePageSetup:
  390.                     do_page_setup_mi();
  391.                     break;
  392.                 case miFilePrintWindow:
  393.                     do_print_mi();
  394.                     break;
  395.                 case miFileQuit:
  396.                     quit_the_game();
  397.                     break;
  398.             }
  399.             break;
  400.         case mEdit:
  401.             /* handledbyda = SystemEdit(menuitem-1); */
  402.             switch (menuitem)  {
  403.                 case miEditCut:
  404.                     /* disband_selection(); */
  405.                     /* (should depend on whether this is a map or a text field) */
  406.                     break;
  407.                 case miEditSelectAll:
  408.                     do_select_all_mi();
  409.                     break;
  410. #ifdef DESIGNERS
  411.                 case miEditDesign:
  412.                     if (!dside->designer) {
  413.                         enable_designing(FALSE);
  414.                     } else {
  415.                         disable_designing();
  416.                     }
  417.                     break;
  418. #endif
  419.             }
  420.             break;
  421.         case mFind:
  422.             switch (menuitem) {
  423.                 case miFindPrevious:
  424.                     do_find_previous_mi();
  425.                     break;
  426.                 case miFindNext:
  427.                     do_find_next_mi();
  428.                     break;
  429.                 case miFindLocation:
  430.                     do_find_location_mi();
  431.                     break;
  432.                 case miFindUnitByName:
  433.                     do_find_unit_by_name_mi();
  434.                     break;
  435.                 case miFindSelected:
  436.                     do_find_selected_mi();
  437.                     break;
  438.             }
  439.             break;
  440.         case mPlay:
  441.             switch (menuitem) {
  442.                 case miPlayCloseup:
  443.                     do_closeup_mi();
  444.                     break;
  445.                 case miPlayMove:
  446.                     do_move_mi();
  447.                     break;
  448.                 case miPlayPatrol:
  449.                     do_patrol_mi();
  450.                     break;
  451.                 case miPlayReturn:
  452.                     do_return_mi();
  453.                     break;
  454.                 case miPlayWake:
  455.                     do_wake_mi();
  456.                     break;
  457.                 case miPlaySleep:
  458.                     do_sleep_mi();
  459.                     break;
  460.                 case miPlayDoneMoving:
  461.                     do_done_moving_mi();
  462.                     break;
  463.                 case miPlayBuild:
  464.                     do_construction_mi();
  465.                     break;
  466.                 case miPlayRepair:
  467.                     do_repair_mi();
  468.                     break;
  469.                 case miPlayAttack:
  470.                     do_attack_mi();
  471.                     break;
  472.                 case miPlayOverrun:
  473.                     do_overrun_mi();
  474.                     break;
  475.                 case miPlayFire:
  476.                     do_fire_mi();
  477.                     break;
  478.                 case miPlayDetonate:
  479.                     do_detonate_mi();
  480.                     break;
  481.                 case miPlayTake:
  482.                     break;
  483.                 case miPlayDrop:
  484.                     break;
  485.                 case miPlayGive:
  486.                     /* has submenu mSides */
  487.                     break;
  488.                 case miPlayDisband:
  489.                     do_disband_mi();
  490.                     break;
  491.                 case miPlayRename:
  492.                     do_rename_mi();
  493.                     break;
  494.             }
  495.             break;
  496.         case mSides:
  497.             do_give_unit_mi(menuitem);
  498.             break;
  499.         case mSide:
  500.             switch (menuitem) {
  501.                 case miSideCloseup:
  502.                     break;
  503.                 case miSideFinishedTurn:
  504.                     finish_turn(dside);
  505.                     break;
  506.                 case miSideMoveOnClick:
  507.                     moveonclick_mi();
  508.                     break;
  509.                 case miSideAutoSelect:
  510.                     autoselect_mi();
  511.                     break;
  512.                 case miSideAutoFinish:
  513.                     /* Toggle auto-finish for turns. */
  514.                     set_autofinish(dside, !dside->autofinish);
  515.                     break;
  516.                 case miSideSound:
  517.                     playsounds = !playsounds;
  518.                     break;
  519.                 case miSideRename:
  520.                     side_rename_dialog(dside);
  521.                     break;
  522.             }
  523.             break;
  524.         case mWindows:
  525.             switch (menuitem) {
  526.                 case miWindowsGame:
  527.                     if (gamewin == nil) {
  528.                         create_game_window();
  529.                     }
  530.                     ShowWindow(gamewin);
  531.                     SelectWindow(gamewin);
  532.                     break;
  533.                 case miWindowsHistory:
  534.                     if (historywin == nil) {
  535.                         create_history_window();
  536.                     }
  537.                     ShowWindow(historywin);
  538.                     SelectWindow(historywin);
  539.                     break;
  540.                 case miWindowsConstruction:
  541.                     enable_construction();
  542.                     break;
  543.                 /* should have agreements list etc handling here also */
  544.                 case miWindowsNewList:
  545.                     create_list();
  546.                     break;
  547.                 case miWindowsNewMap:
  548.                     create_map(5 /* should be a pref */);
  549.                     break;
  550.                 case miWindowsWorldMap:
  551.                     if (worldmapwin == nil) {
  552.                         int power, winwid = 200;
  553.  
  554.                         for (power = 0; power < NUMPOWERS; ++power) {
  555.                             if (area.width * hws[power] <= winwid
  556.                                 && area.width * hws[power+1] > winwid) break;
  557.                         }
  558.                         worldmap = create_map(power);
  559.                         worldmap->drawothermaps = TRUE;
  560.                         /* (should be in survey mode too?) */
  561.                         worldmapwin = worldmap->window;
  562.                     }
  563.                     ShowWindow(worldmapwin);
  564.                     SelectWindow(worldmapwin);
  565.                     break;
  566.                 default:
  567.                     win = winmenuwins[menuitem - miWindowsFirst];
  568.                     if (win != nil) {
  569.                         SelectWindow(win);
  570.                     }
  571.                     break;
  572.             }
  573.             break;
  574.         case mViewMap:
  575.             switch (menuitem)  {
  576.                 case miViewCloser:
  577.                     magnify_map(map_from_window(FrontWindow()), 1);
  578.                     break;
  579.                 case miViewFarther:
  580.                     magnify_map(map_from_window(FrontWindow()), -1);
  581.                     break;
  582.                 case miViewNames:
  583.                     toggle_map_names(map_from_window(FrontWindow()));
  584.                     break;
  585.                 case miViewPeople:
  586.                     toggle_map_people(map_from_window(FrontWindow()));
  587.                     break;
  588.                 case miViewElevations:
  589.                     toggle_map_elevations(map_from_window(FrontWindow()));
  590.                     break;
  591.                 case miViewDaylight:
  592.                     toggle_map_lighting(map_from_window(FrontWindow()));
  593.                     break;
  594.                 case miViewGrid:
  595.                     toggle_map_grid(map_from_window(FrontWindow()));
  596.                     break;
  597.                 case miViewTopline:
  598.                     toggle_map_topline(map_from_window(FrontWindow()));
  599.                     break;
  600.                 case miViewOtherMaps:
  601.                     toggle_map_other_maps(map_from_window(FrontWindow()));
  602.                     break;
  603.             }
  604.             break;
  605.         case mViewWeather:
  606.             switch (menuitem)  {
  607.                 case miWeatherTemperature:
  608.                     toggle_map_temperature(map_from_window(FrontWindow()));
  609.                     break;
  610.                 case miWeatherWinds:
  611.                     toggle_map_winds(map_from_window(FrontWindow()));
  612.                     break;
  613.                 case miWeatherClouds:
  614.                     toggle_map_clouds(map_from_window(FrontWindow()));
  615.                     break;
  616.                 case miWeatherStorms:
  617.                     toggle_map_storms(map_from_window(FrontWindow()));
  618.                     break;
  619.             }
  620.             break;
  621.         case mViewList:
  622.             switch (menuitem)  {
  623.                 case miViewByType:
  624.                     set_list_sorting(list_from_window(FrontWindow()), bytype, menuitem);
  625.                     break;
  626.                 case miViewByName:
  627.                     set_list_sorting(list_from_window(FrontWindow()), byname, menuitem);
  628.                     break;
  629.                 case miViewBySide:
  630.                     set_list_sorting(list_from_window(FrontWindow()), byside, menuitem);
  631.                     break;
  632.                 case miViewByActOrder:
  633.                     set_list_sorting(list_from_window(FrontWindow()), byactorder, menuitem);
  634.                     break;
  635.                 case miViewByLocation:
  636.                     set_list_sorting(list_from_window(FrontWindow()), bylocation, menuitem);
  637.                     break;
  638.                 case miViewIconSize:
  639.                     toggle_list_large_icons(list_from_window(FrontWindow()));
  640.                     break;
  641.             }
  642.             break;
  643.         case mAITypes:
  644.             switch (menuitem) {
  645.                 case 1:
  646.                     if (side_has_ai(dside)) {
  647.                         set_side_ai(dside, NULL);
  648.                     }
  649.                     break;
  650.                 case 2:
  651.                     if (!side_has_ai(dside)) {
  652.                         set_side_ai(dside, "mplayer");
  653.                     }
  654.                     break;
  655.             }
  656.             break;
  657.         case mMagnifications:
  658.             set_map_mag(map_from_window(FrontWindow()), menuitem - 1);
  659.             break;
  660.         case mMaterialTypes:
  661.             toggle_map_materials(map_from_window(FrontWindow()), menuitem - 1);
  662.             break;
  663.     }
  664.     HiliteMenu(0);
  665. }
  666.  
  667. /* Display the "About..." box. */
  668.  
  669. /* This dialog does double duty - initially it chooses New/Open/Connect/Quit,
  670.    later on it's just a normal About box. */
  671.  
  672. do_about_box()
  673. {
  674.     short ditem;
  675.     Str255 tmpstr;
  676.     WindowPtr win;
  677.     PicHandle pic;
  678.     short itemtype;  Handle itemhandle;  Rect itemrect;
  679.  
  680.     win = GetNewDialog(dAbout, NULL, (DialogPtr) -1L);
  681.     /* Fill in the kernel's version and copyright. */
  682.     GetDItem(win, diAboutVersion, &itemtype, &itemhandle, &itemrect);
  683.     c2p(version_string(), tmpstr);
  684.     SetIText(itemhandle, tmpstr);
  685.     GetDItem(win, diAboutCopyright, &itemtype, &itemhandle, &itemrect);
  686.     c2p(copyright_string(), tmpstr);
  687.     SetIText(itemhandle, tmpstr);
  688.     /* Substitute a color picture if possible. */
  689.     if (hasColorQD) {
  690.         GetDItem(win, diAboutPicture, &itemtype, &itemhandle, &itemrect);
  691.         if ((pic = (PicHandle) GetResource('PICT', pSplashColor)) != nil) {
  692.             SetDItem(win, diAboutPicture, itemtype, (Handle) pic, &itemrect);
  693.         }
  694.     }
  695.     ShowWindow(win);
  696.     SelectWindow(win);
  697.     draw_default_button(win, diAboutOK);
  698.     ModalDialog(NULL, &ditem);
  699.     /* Just return, no matter what input. */
  700.     HideWindow(win);
  701.     DisposDialog(win);
  702. }
  703.  
  704. /* This routine does both "save" and "save as". */
  705.  
  706. save_the_game(askname, quitting)
  707. int askname, quitting;
  708. {
  709.     extern CursHandle watchcursor;
  710.  
  711. #ifdef DESIGNERS
  712.     /* Do the selective save only if we're not shutting down Xconq. */
  713.     if (dside->designer && !quitting) {
  714.         designer_save_dialog();
  715.     } else
  716. #endif
  717.     if (askname || cursavename == NULL) {
  718.         if (cursavename == NULL) cursavename = savefile_name();
  719.         /* should bring up dialog to choose name */
  720.         /* Do the save proper. */
  721.         SetCursor(*watchcursor);
  722.         write_entire_game_state(cursavename);
  723.         setfiletype(cursavename);
  724.     } else {
  725.         /* Just save to the same file as before. */
  726.         SetCursor(*watchcursor);
  727.         write_entire_game_state(cursavename);
  728.         setfiletype(cursavename);
  729.     }
  730. /*    adjust_cursor(?, ?); */
  731. }
  732.  
  733. set_preferences()
  734. {
  735.     short done = FALSE, ditem;
  736.     DialogPtr win;
  737.     short itemtype;  Handle itemhandle;  Rect itemrect;
  738.     extern int checkpointinterval;
  739.  
  740.     /* (should have gotten prefs from file already) */
  741.     win = GetNewDialog(dPreferences, NULL, (DialogPtr) -1L);
  742.     /* Set the current preferences into the items. */
  743.     GetDItem(win, diPrefsGrid, &itemtype, &itemhandle, &itemrect);
  744.     SetCtlValue((ControlHandle) itemhandle, defaultdrawgrid);
  745.     GetDItem(win, diPrefsNames, &itemtype, &itemhandle, &itemrect);
  746.     SetCtlValue((ControlHandle) itemhandle, defaultdrawnames);
  747.     GetDItem(win, diPrefsCheckpoint, &itemtype, &itemhandle, &itemrect);
  748.     SetCtlValue((ControlHandle) itemhandle, (checkpointinterval > 0));
  749.     ShowWindow(win);
  750.     while (!done) {
  751.         ModalDialog(NULL, &ditem);
  752.         switch (ditem) {
  753.             case diPrefsOK:
  754.                 /* Actually change the program's variables. */
  755.                 GetDItem(win, diPrefsGrid, &itemtype, &itemhandle, &itemrect);
  756.                 defaultdrawgrid = GetCtlValue((ControlHandle) itemhandle);
  757.                 GetDItem(win, diPrefsNames, &itemtype, &itemhandle, &itemrect);
  758.                 defaultdrawnames = GetCtlValue((ControlHandle) itemhandle);
  759.                 GetDItem(win, diPrefsCheckpoint, &itemtype, &itemhandle, &itemrect);
  760.                 checkpointinterval = (GetCtlValue((ControlHandle) itemhandle) ? 5 : 0);
  761.                 /* Fall into next case. */
  762.             case diPrefsCancel:
  763.                 done = TRUE;
  764.                 break;
  765.             case diPrefsGrid:
  766.             case diPrefsNames:
  767.                 /* Toggle check boxes. */
  768.                 GetDItem(win, ditem, &itemtype, &itemhandle, &itemrect);
  769.                 SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
  770.                 break;
  771.             case diPrefsCheckpoint:
  772.                 GetDItem(win, ditem, &itemtype, &itemhandle, &itemrect);
  773.                 SetCtlValue((ControlHandle) itemhandle, !GetCtlValue((ControlHandle) itemhandle));
  774.                 /* Should enable/disable interval-setting ditems. */
  775.                 break;
  776.             case diPrefsInterval:
  777.                 break;
  778.         }
  779.     }
  780.     DisposDialog(win);
  781. }
  782.  
  783. /*THPrint printrecordhandle = nil;*/
  784.  
  785. maybe_init_print()
  786. {
  787. /*    if (printrecordhandle == nil) {
  788.         printrecordhandle = (THPrint) NewHandle(sizeof(TPrint));
  789.         PrOpen();
  790.         PrintDefault(printrecordhandle);
  791.     } */
  792. }
  793.  
  794. do_page_setup_mi()
  795. {
  796.     maybe_init_print();
  797. /*    PrStlDialog(printrecordhandle); */
  798. }
  799.  
  800. /* Handle printing.  What gets printed depends on which window is in front. */
  801.  
  802. do_print_mi()
  803. {
  804.     Map *map;
  805.     List *list;
  806.  
  807.     maybe_init_print();
  808. /*    if (!PrJobDialog(printrecordhandle)) return; */
  809.     if ((map = map_from_window(FrontWindow())) != NULL) {
  810.         print_map(map);
  811.     } else if ((list = list_from_window(FrontWindow())) != NULL) {
  812.         print_list(list);
  813.     } else {
  814.         /* (should at least be able to print game desc) */
  815.     }
  816. }
  817.  
  818. /* Attempt to quit. */
  819.  
  820. /* (should warn if quitting is tantamount to resigning) */
  821. /* (should close any open windows left) */
  822.  
  823. quit_the_game()
  824. {
  825.     extern int gamestatesafe, interfacestatesafe;
  826.     extern int endofgame;
  827.     Boolean closed;
  828.     WindowPtr win;
  829.  
  830.     if (endofgame) {
  831.         /* Game is over, nothing to save. */
  832.         ExitToShell();
  833.     } else if (!gamestatesafe || !interfacestatesafe) {
  834.         switch (CautionAlert(aQuitGame, nil)) {
  835.             case aiQuitGameOK:
  836.                 /* (should maybe do game resignation, update other sides) */
  837.                 SetCursor(*watchcursor);
  838.                 save_the_game(FALSE, TRUE);
  839.                 SetCursor(&qd.arrow);
  840.                 ExitToShell();
  841.                 break;
  842.             case aiQuitGameCancel:
  843.                 break;
  844.             case aiQuitGameDontSave:
  845. #if 0
  846.     switch (CautionAlert(aResignGame, nil)) {
  847.         case aiResignOK:
  848.             /* (should do game resignation, update other sides) */
  849.             break;
  850.         case aiResignCancel:
  851.             break;
  852.     }
  853. #endif
  854.                 ExitToShell();
  855.                 break;
  856.         }
  857.     } else {
  858.         /* (should still confirm that we're not avoiding our fate...) */
  859.         ExitToShell();
  860.     }
  861. }
  862.  
  863. do_select_all_mi()
  864. {
  865.     int i;
  866.     Map *map;
  867.     Unit *unit;
  868.     Side *side;
  869.     
  870.     if ((map = map_from_window(FrontWindow())) != NULL) {
  871.         for_all_units(side, unit) {
  872.             if (side_may_select(unit)) {
  873.                 select_unit_on_map(map, unit);
  874.             }
  875.         }
  876.         /* Do all the drawing at once. */
  877.         draw_selections(map);
  878.     }
  879. }
  880.  
  881. do_find_previous_mi()
  882. {
  883.     Map *map;
  884.     
  885.     if ((map = map_from_window(FrontWindow())) != NULL) {
  886.         select_previous_unit(map);
  887.     }
  888. }
  889.  
  890. do_find_next_mi()
  891. {
  892.     Map *map;
  893.     
  894.     if ((map = map_from_window(FrontWindow())) != NULL) {
  895.         select_next_mover(map);
  896.     }
  897. }
  898.  
  899. /* (should ask for x,y coords, focus/center on that position) */
  900.  
  901. do_find_location_mi()
  902. {
  903.     Map *map;
  904.     
  905.     if ((map = map_from_window(FrontWindow())) != NULL) {
  906.     }
  907. }
  908.  
  909. /* (should ask for a textual name/select from a gazetteer, scroll to that unit) */
  910.  
  911. do_find_unit_by_name_mi()
  912. {
  913.     Map *map;
  914.     
  915.     if ((map = map_from_window(FrontWindow())) != NULL) {
  916.     }
  917. }
  918.  
  919. do_find_selected_mi()
  920. {
  921.     Map *map;
  922.     List *list;
  923.     
  924.     if ((map = map_from_window(FrontWindow())) != NULL) {
  925.     } else if ((list = list_from_window(FrontWindow())) != NULL) {
  926.         scroll_to_selected_unit_in_list(list);
  927.     } else {
  928.         /* nothing to do */
  929.     }
  930. }
  931.  
  932. /* Menu items/commands for unit play action. */
  933.  
  934. apply_to_all_selected(fn)
  935. int (*fn)();
  936. {
  937.     int i, numcould = 0, numnot = 0;
  938.     Map *map;  List *list;  UnitCloseup *closeup;
  939.     Unit *unit;
  940.  
  941.     if (fn == NULL) return;
  942.     if ((map = map_from_window(FrontWindow())) != NULL) {
  943.         for (i = 0; i < map->numselections; ++i) {
  944.             if ((unit = map->selections[i]) != NULL) {
  945.                 (*fn)(unit);
  946.             }
  947.         }
  948.     } else if ((list = list_from_window(FrontWindow())) != NULL) {
  949.         if ((unit = (Unit *) selected_unit_in_list(list)) != NULL) {
  950.             (*fn)(unit);
  951.         }
  952.     } else if ((closeup = unit_closeup_from_window(FrontWindow())) != NULL) {
  953.         if ((unit = closeup->unit) != NULL) {
  954.             (*fn)(unit);
  955.         }
  956.     }
  957. }
  958.  
  959. do_closeup_mi()
  960. {
  961.     int i;
  962.     Map *map;  List *list;  UnitCloseup *unitcloseup;
  963.     Unit *unit;
  964.     
  965.     if ((map = map_from_window(FrontWindow())) != NULL) {
  966.         for (i = 0; i < map->numselections; ++i) {
  967.             if ((unit = map->selections[i]) != NULL) {
  968.                 if ((unitcloseup = find_unit_closeup(unit)) != NULL) {
  969.                     ShowWindow(unitcloseup->window);
  970.                     SelectWindow(unitcloseup->window);
  971.                 } else {
  972.                     create_unit_closeup(unit);
  973.                 }
  974.             }
  975.         }
  976.     } else if ((list = list_from_window(FrontWindow())) != NULL) {
  977.         if ((unit = (Unit *) selected_unit_in_list(list)) != NULL) {
  978.             if ((unitcloseup = find_unit_closeup(unit)) != NULL) {
  979.                 ShowWindow(unitcloseup->window);
  980.                 SelectWindow(unitcloseup->window);
  981.             } else {
  982.                 create_unit_closeup(unit);
  983.             }
  984.         }
  985.     }
  986. }
  987.  
  988. do_move_mi()
  989. {
  990.     SysBeep(20);
  991. }
  992.  
  993. do_patrol_mi()
  994. {
  995.     SysBeep(20);
  996. }
  997.  
  998. do_one_return(unit)
  999. Unit *unit;
  1000. {
  1001.     set_resupply_task(unit);
  1002. }
  1003.  
  1004. do_return_mi()
  1005. {
  1006.     apply_to_all_selected(do_one_return);    
  1007.     /* If everybody that was asked to do the action couldn't, beep once. */
  1008.     /* if (numcould == 0 && numnot > 0) SysBeep(20); */
  1009. }
  1010.  
  1011. do_wake_mi()
  1012. {
  1013.     do_reserve_command(FALSE, FALSE);
  1014.     do_sleep_command(FALSE, FALSE);
  1015. }
  1016.  
  1017. do_sleep_mi()
  1018. {
  1019.     do_sleep_command(TRUE, FALSE);
  1020. }
  1021.  
  1022. do_done_moving_mi()
  1023. {
  1024.     do_reserve_command(TRUE, FALSE);
  1025. }
  1026.  
  1027. int tmpcmdarg;
  1028. int tmprecurse;
  1029.  
  1030. do_one_reserve(unit)
  1031. Unit *unit;
  1032. {
  1033.     set_unit_reserve(dside, unit, tmpcmdarg, tmprecurse);
  1034. }
  1035.  
  1036. do_reserve_command(value, recurse)
  1037. int value, recurse;
  1038. {
  1039.     tmpcmdarg = value;
  1040.     tmprecurse = recurse;
  1041.     apply_to_all_selected(do_one_reserve);    
  1042. }
  1043.  
  1044. do_one_asleep(unit)
  1045. Unit *unit;
  1046. {
  1047.     set_unit_asleep(dside, unit, tmpcmdarg, tmprecurse);
  1048. }
  1049.  
  1050. do_sleep_command(value, recurse)
  1051. int value, recurse;
  1052. {
  1053.     tmpcmdarg = value;
  1054.     tmprecurse = recurse;
  1055.     apply_to_all_selected(do_one_asleep);    
  1056. }
  1057.  
  1058. do_one_clear_plan(unit)
  1059. Unit *unit;
  1060. {
  1061.     if (unit->plan) {
  1062.         set_unit_plan_type(dside, unit, PLAN_NONE);
  1063.     }
  1064. }
  1065.  
  1066. do_clear_plan_command()
  1067. {
  1068.     apply_to_all_selected(do_one_clear_plan);    
  1069. }
  1070.  
  1071. do_one_ai_control(unit)
  1072. Unit *unit;
  1073. {
  1074.     if (unit->plan) {
  1075.         set_unit_ai_control(dside, unit, !unit->plan->aicontrol);
  1076.     }
  1077. }
  1078.  
  1079. do_ai_control_command()
  1080. {
  1081.     apply_to_all_selected(do_one_ai_control);    
  1082. }
  1083.  
  1084. do_construction_mi()
  1085. {
  1086.     int i;
  1087.     Map *map;  List *list;  UnitCloseup *closeup;
  1088.     Unit *unit;
  1089.     
  1090.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1091.         for (i = 0; i < map->numselections; ++i) {
  1092.             if ((unit = map->selections[i]) != NULL) {
  1093.                 if (can_build(unit)) {  /* and completers and researchers too? */
  1094.                     enable_construction();
  1095.                     select_unit_in_construction_window(unit);
  1096.                     return;
  1097.                 }
  1098.             }
  1099.         }
  1100.     } else if ((list = list_from_window(FrontWindow())) != NULL) {
  1101.         if ((unit = (Unit *) selected_unit_in_list(list)) != NULL) {
  1102.                 if (can_build(unit)) {  /* and completers and researchers too? */
  1103.                     enable_construction();
  1104.                     select_unit_in_construction_window(unit);
  1105.                     return;
  1106.                 }
  1107.         }
  1108.     } else if ((closeup = unit_closeup_from_window(FrontWindow())) != NULL) {
  1109.         if ((unit = closeup->unit) != NULL) {
  1110.                 if (can_build(unit)) {  /* and completers and researchers too? */
  1111.                     enable_construction();
  1112.                     select_unit_in_construction_window(unit);
  1113.                     return;
  1114.                 }
  1115.         }
  1116.     }
  1117. }
  1118.  
  1119. /* Create and/or bring up the construction planning window. */
  1120.  
  1121. enable_construction()
  1122. {
  1123.     if (constructionwin == nil) {
  1124.         create_construction_window();
  1125.     }
  1126.     if (constructionwin != nil) {
  1127.         reinit_construction_lists();
  1128.         ShowWindow(constructionwin);
  1129.         SelectWindow(constructionwin);
  1130.     }
  1131. }
  1132.  
  1133. do_repair_mi()
  1134. {
  1135.     apply_to_all_selected(NULL);    
  1136. }
  1137.  
  1138. /* (should find one unit to attack, do modal dialog if != 1) */
  1139.  
  1140. do_attack_mi()
  1141. {
  1142.     int i;
  1143.     Map *map;
  1144.     Unit *atker, *other;
  1145.     Side *side;
  1146.     
  1147.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1148.         for (i = 0; i < map->numselections; ++i) {
  1149.             if ((atker = map->selections[i]) != NULL) {
  1150.                 for_all_units(side, other) {
  1151.                     if (other != atker
  1152.                         && other->side != atker->side
  1153.                         && distance(atker->x, atker->y, other->x, other->y) == 1) {
  1154.                             prep_attack_action(atker, atker, other, 100);
  1155.                             break;
  1156.                     }
  1157.                 }
  1158.             }
  1159.         }
  1160.     }
  1161. }
  1162.  
  1163. do_attack_command()
  1164. {
  1165.     int i, x, y, numcould = 0, numnot = 0;
  1166.     Point target;
  1167.     Map *map;
  1168.     Unit *atker, *other;
  1169.     Side *side;
  1170.     
  1171.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1172.         GetMouse(&target);
  1173.         nearest_unit(map, target.h, target.v, &other);
  1174.         if (other != NULL) {
  1175.             for (i = 0; i < map->numselections; ++i) {
  1176.                 if ((atker = map->selections[i]) != NULL) {
  1177.                     if (other != atker
  1178.                         && other->side != atker->side) {
  1179.                         if (distance(atker->x, atker->y, other->x, other->y) <= 1
  1180.                             && valid(check_attack_action(atker, atker, other, 100))) {
  1181.                             prep_attack_action(atker, atker, other, 100);
  1182.                             ++numcould;
  1183.                         } else if (valid(check_fire_at_action(atker, atker, other, -1))) {
  1184.                             prep_fire_at_action(atker, atker, other, -1);
  1185.                             ++numcould;
  1186.                         } else {
  1187.                             ++numnot;
  1188.                         }
  1189.                     } else {
  1190.                     }
  1191.                 }
  1192.             }
  1193.         } else {
  1194.             /* (should let units fire into empty cell) */
  1195.         }
  1196.     }
  1197.     /* If nobody could do the action, beep once. */
  1198.     if (numcould == 0 && numnot > 0) SysBeep(20);
  1199. }
  1200.  
  1201. do_overrun_mi()
  1202. {
  1203.     /* (should loop until mouse clicked in map) */
  1204.     SysBeep(20);
  1205. }
  1206.  
  1207. do_fire_mi()
  1208. {
  1209.     if (modaltool == 0) {
  1210.         modaltool = 2;
  1211.     }
  1212. }
  1213.  
  1214. do_fire_command()
  1215. {
  1216.     int i, x, y, numcould = 0, numnot = 0;
  1217.     Point target;
  1218.     Map *map;
  1219.     Unit *atker, *other;
  1220.     Side *side;
  1221.     
  1222.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1223.         GetMouse(&target);
  1224.         nearest_unit(map, target.h, target.v, &other);
  1225.         if (other != NULL) {
  1226.             for (i = 0; i < map->numselections; ++i) {
  1227.                 if ((atker = map->selections[i]) != NULL && valid_selection(atker)) {
  1228.                     if (other != atker
  1229.                         && other->side != atker->side
  1230.                         && valid(check_fire_at_action(atker, atker, other, -1))) {
  1231.                         prep_fire_at_action(atker, atker, other, -1);
  1232.                         ++numcould;
  1233.                     } else {
  1234.                         ++numnot;
  1235.                     }
  1236.                 }
  1237.             }
  1238.         } else {
  1239.             /* (should let units fire into empty cell) */
  1240.         }
  1241.     }
  1242.     /* If nobody could do the action, beep once. */
  1243.     if (numcould == 0 && numnot > 0) {
  1244.         SysBeep(20);
  1245.         return FALSE;
  1246.     } else {
  1247.         return TRUE;
  1248.     }
  1249. }
  1250.  
  1251. /* (should decide how to detonate based on selections and modal input) */
  1252.  
  1253. do_one_detonate(unit)
  1254. Unit *unit;
  1255. {
  1256.     prep_detonate_action(unit, unit, unit->x, unit->y, unit->z);
  1257. }
  1258.  
  1259. do_detonate_mi()
  1260. {
  1261.     apply_to_all_selected(do_one_detonate);
  1262. }
  1263.  
  1264. /* This command samples the current mouse to get the desired attack location. */
  1265.  
  1266. do_detonate_command()
  1267. {
  1268.     int i, x, y;
  1269.     Point detpoint;
  1270.     Map *map;
  1271.     Unit *unit;
  1272.     
  1273.     if ((map = map_from_window(FrontWindow())) != NULL) {
  1274.         GetMouse(&detpoint);
  1275.         nearest_cell(map, detpoint.h, detpoint.v, &x, &y);
  1276.         for (i = 0; i < map->numselections; ++i) {
  1277.             if ((unit = map->selections[i]) != NULL) {
  1278.                 prep_detonate_action(unit, unit, x, y, unit->z);
  1279.             }
  1280.         }
  1281.     }
  1282. }
  1283.  
  1284. Side *tmpcmdside;
  1285.  
  1286. do_one_give_unit(unit)
  1287. Unit *unit;
  1288. {
  1289.     if (unit->side == tmpcmdside) return;
  1290. #ifdef DESIGNERS
  1291.     if (dside->designer) {
  1292.         unit_changes_side(unit, tmpcmdside, -1, -1);
  1293.         update_unit_display(dside, unit, TRUE);
  1294.     } else
  1295. #endif /* DESIGNERS */
  1296.     {
  1297.         prep_change_side_action(unit, unit, tmpcmdside);
  1298.     }
  1299. }
  1300.  
  1301. do_give_unit_mi(mi)
  1302. int mi;
  1303. {
  1304.     Side *side = side_n(mi); /* note that side_n returns NULL for mi == numsides */
  1305.     
  1306.     apply_to_all_selected(do_one_give_unit);
  1307. }
  1308.  
  1309. do_one_disband(unit)
  1310. Unit *unit;
  1311. {
  1312.     /* (should call a designer_disband routine) */
  1313. #ifdef DESIGNERS
  1314.     if (dside->designer) {
  1315.         kill_unit(unit, -1);
  1316.     } else
  1317. #endif /* DESIGNERS */
  1318.     if (!completed(unit)) {
  1319.         kill_unit(unit, H_UNIT_DISBANDED);
  1320.     } else if (unit->act && unit->act->acp > 0) {
  1321.         prep_disband_action(unit, unit);
  1322.     } else {
  1323.         /* try to find a nearby unit to do it */
  1324.     }
  1325. }
  1326.  
  1327. do_disband_mi()
  1328. {
  1329.     apply_to_all_selected(do_one_disband);
  1330. }
  1331.  
  1332. do_one_rename(unit)
  1333. Unit *unit;
  1334. {
  1335.     unit_rename_dialog(unit);
  1336. }
  1337.  
  1338. /* This just renames the first of the selected units. */
  1339.  
  1340. do_rename_mi()
  1341. {
  1342.     apply_to_all_selected(do_one_rename);
  1343. }
  1344.  
  1345. moveonclick_mi()
  1346. {
  1347.     Map *frontmap = map_from_window(FrontWindow());
  1348.  
  1349.     if (frontmap) {
  1350.         frontmap->moveonclick = !frontmap->moveonclick;
  1351.         /* (should force updates of map windows to reflect?) */
  1352.     } else {
  1353.         defaultmoveonclick = !defaultmoveonclick;
  1354.     }
  1355. }
  1356.  
  1357. autoselect_mi()
  1358. {
  1359.     Map *frontmap = map_from_window(FrontWindow());
  1360.     extern Unit *curunit;
  1361.  
  1362.     if (frontmap) {
  1363.         frontmap->autoselect = !frontmap->autoselect;
  1364.         frontmap->curunit = NULL; /* maybe not a good idea? */
  1365.         /* (should force updates of map windows to reflect?) */
  1366.     } else {
  1367.         defaultautoselect = !defaultautoselect;
  1368.     }
  1369. }
  1370.  
  1371. adjust_menu_item(menu, item, value)
  1372. MenuHandle menu;
  1373. int item, value;
  1374. {
  1375.     if (value) {
  1376.         EnableItem(menu, item);
  1377.     } else {
  1378.         DisableItem(menu, item);
  1379.     }
  1380. }
  1381.  
  1382. /* The state of menu items changes to reflect selected units, etc. */
  1383.  
  1384. adjust_menus()
  1385. {
  1386.     int i, m, nextmi, numwins;
  1387.     MenuHandle menu;
  1388.     Map *frontmap;
  1389.     List *frontlist;
  1390.     UnitCloseup *frontcloseup;
  1391.     Unit *unit;
  1392.  
  1393.     frontmap = map_from_window(FrontWindow());
  1394.     frontlist = list_from_window(FrontWindow());
  1395.     frontcloseup = unit_closeup_from_window(FrontWindow());
  1396.     /* Certain menus need to be built after the game is running. */
  1397.     if (menus_tweakable()) {
  1398.         build_material_type_menu();
  1399.         build_side_menu();
  1400.         build_ai_type_menu();
  1401.     }
  1402. #if 0
  1403.     if (is_da_window(FrontWindow())) {
  1404.         if ((menu = GetMHandle(mEdit)) != nil) {
  1405.         }
  1406.         return;
  1407.     }
  1408. #endif
  1409.     if ((menu = GetMHandle(mFile)) != nil) {
  1410.         /* Availability of file menu items depends on whether we're in a game. */
  1411.         adjust_menu_item(menu, miFileNew, !gamedefined);
  1412.         adjust_menu_item(menu, miFileOpen, !gamedefined);
  1413.         adjust_menu_item(menu, miFileConnect, !gamedefined && can_connect());
  1414.         adjust_menu_item(menu, miFileSave, menus_tweakable());
  1415.         adjust_menu_item(menu, miFileSaveAs, menus_tweakable());
  1416.     }
  1417.     if ((menu = GetMHandle(mEdit)) != nil) {
  1418.         /* Edit menu is always available, but most items may be disabled. */
  1419.         /* (should do the other items also) */
  1420.         adjust_menu_item(menu, miEditSelectAll, menus_tweakable());
  1421.         if (menus_tweakable()) {
  1422. #ifdef DESIGNERS
  1423.             CheckItem(menu, miEditDesign, dside->designer);
  1424. #else
  1425.             DisableItem(menu, miEditDesign);
  1426. #endif /* DESIGNERS */
  1427.         }
  1428.     }
  1429.     if ((menu = GetMHandle(mFind)) != nil) {
  1430.         if (gameinited) {
  1431.             EnableItem(menu, 0);
  1432.             adjust_menu_item(menu, miFindPrevious, menus_tweakable());
  1433.             adjust_menu_item(menu, miFindNext, menus_tweakable());
  1434.             adjust_menu_item(menu, miFindLocation, menus_tweakable());
  1435.             adjust_menu_item(menu, miFindUnitByName, TRUE);
  1436.             adjust_menu_item(menu, miFindSelected, TRUE);
  1437.         } else {
  1438.             /* We're not even in a game yet, turn entire menu off. */
  1439.             DisableItem(menu, 0);
  1440.         }
  1441.     }
  1442.     if ((menu = GetMHandle(mPlay)) != nil) {
  1443.         if (menus_tweakable()) {
  1444.             EnableItem(menu, 0);
  1445.             /* Disable everything first, then selectively re-enable. */
  1446.             DisableItem(menu, miPlayCloseup);
  1447.             DisableItem(menu, miPlayMove);
  1448.             DisableItem(menu, miPlayPatrol);
  1449.             DisableItem(menu, miPlayReturn);
  1450.             DisableItem(menu, miPlayWake);
  1451.             DisableItem(menu, miPlaySleep);
  1452.             DisableItem(menu, miPlayDoneMoving);
  1453.             DisableItem(menu, miPlayBuild);
  1454.             DisableItem(menu, miPlayRepair);
  1455.             DisableItem(menu, miPlayAttack);
  1456.             DisableItem(menu, miPlayOverrun);
  1457.             DisableItem(menu, miPlayFire);
  1458.             DisableItem(menu, miPlayDetonate);
  1459.             DisableItem(menu, miPlayTake);
  1460.             DisableItem(menu, miPlayDrop);
  1461.             DisableItem(menu, miPlayGive);
  1462.             DisableItem(menu, miPlayDisband);
  1463.             DisableItem(menu, miPlayRename);
  1464.             /* Note that command enabling is accumulative for all units. */
  1465.             if (frontmap != NULL) {
  1466.                 for (i = 0; i < frontmap->numselections; ++i) {
  1467.                     if ((unit = frontmap->selections[i]) != NULL) {
  1468.                         enable_commands_for_unit(menu, unit);
  1469.                     }
  1470.                 }
  1471.             } else if (frontlist != NULL) {
  1472.                 if ((unit = (Unit *) selected_unit_in_list(frontlist)) != NULL) {
  1473.                     enable_commands_for_unit(menu, unit);
  1474.                 }
  1475.             } else if (frontcloseup != NULL) {
  1476.                 if ((unit = frontcloseup->unit) != NULL) {
  1477.                     enable_commands_for_unit(menu, unit);
  1478.                 }
  1479.             }
  1480.         } else {
  1481.             /* We're not even in a valid game state yet, turn entire menu off. */
  1482.             DisableItem(menu, 0);
  1483.         }
  1484.     }
  1485.     if ((menu = GetMHandle(mSide)) != nil) {
  1486.         if (menus_tweakable()) {
  1487.             EnableItem(menu, 0);
  1488.             CheckItem(menu, miSideMoveOnClick,
  1489.                       (frontmap ? frontmap->moveonclick : defaultmoveonclick));
  1490.             CheckItem(menu, miSideAutoSelect,
  1491.                       (frontmap ? frontmap->autoselect : defaultautoselect));
  1492.             CheckItem(menu, miSideAutoFinish, dside->autofinish);
  1493.             CheckItem(menu, miSideSound, playsounds);
  1494.             if (dside->nameslocked) {
  1495.                 DisableItem(menu, miSideRename);
  1496.             } else {
  1497.                 EnableItem(menu, miSideRename);
  1498.             }
  1499.         } else {
  1500.             /* We're not even in a game yet, turn entire menu off. */
  1501.             DisableItem(menu, 0);
  1502.         }
  1503.     }
  1504.     if ((menu = GetMHandle(mWindows)) != nil) {
  1505.         if (gameinited) {
  1506.             EnableItem(menu, 0);
  1507.             /* Every item is always enabled. (should be, anyway) */
  1508.             CheckItem(menu, miWindowsGame,
  1509.                 (gamewin && ((WindowPeek) gamewin)->visible));
  1510.             CheckItem(menu, miWindowsHistory,
  1511.                 (historywin && ((WindowPeek) historywin)->visible));
  1512.             if (construction_ever_possible()) {
  1513.                 EnableItem(menu, miWindowsConstruction);
  1514.                 CheckItem(menu, miWindowsConstruction,
  1515.                     (constructionwin && ((WindowPeek) constructionwin)->visible));
  1516.             } else {
  1517.                 DisableItem(menu, miWindowsConstruction);
  1518.             }
  1519.             numwins = CountMItems(menu) - miWindowsFirst;
  1520.             for (i = 0; i < numwins; ++i) {
  1521.                 CheckItem(menu, i + miWindowsFirst, (winmenuwins[i] == FrontWindow()));
  1522.             }
  1523.         } else {
  1524.             /* We're not even in a game yet, turn entire menu off. */
  1525.             DisableItem(menu, 0);
  1526.         }
  1527.     }
  1528.     /* If a map window is frontmost, install and adjust the map view menu. */
  1529.     if (frontmap != NULL) {
  1530.         /* Delete the list view menu if that's what's installed currently. */
  1531.         /* (should be able to flush any non-map-view menu) */
  1532.         if ((menu = GetMHandle(mViewList)) != nil) {
  1533.             DeleteMenu(mViewList);
  1534.         }
  1535.         /* Make sure the map view menu is installed (is always at the end). */
  1536.         InsertMenu(mapviewmenu, 0);
  1537.         if ((menu = GetMHandle(mViewMap)) != nil) {
  1538.             EnableItem(menu, 0);
  1539.             if (frontmap->power == 0) {
  1540.                 DisableItem(menu, miViewFarther);
  1541.             } else {
  1542.                 EnableItem(menu, miViewFarther);
  1543.             }
  1544.             if (frontmap->power == NUMPOWERS-1) {
  1545.                 DisableItem(menu, miViewCloser);
  1546.             } else {
  1547.                 EnableItem(menu, miViewCloser);
  1548.             }
  1549.             EnableItem(menu, miViewGrid);
  1550.             CheckItem(menu, miViewGrid, frontmap->drawgrid);
  1551.             EnableItem(menu, miViewTopline);
  1552.             CheckItem(menu, miViewTopline, (frontmap->toph > 0));
  1553.             EnableItem(menu, miViewNames);
  1554.             CheckItem(menu, miViewNames, frontmap->drawnames);
  1555.             if (people_sides_defined()) {
  1556.                 EnableItem(menu, miViewPeople);
  1557.                 CheckItem(menu, miViewPeople, frontmap->drawpeople);
  1558.             } else {
  1559.                 DisableItem(menu, miViewPeople);
  1560.             }
  1561.             if (elevations_defined()) {
  1562.                 EnableItem(menu, miViewElevations);
  1563.                 CheckItem(menu, miViewElevations, frontmap->drawelevations);
  1564.             } else {
  1565.                 DisableItem(menu, miViewElevations);
  1566.             }
  1567.             if (1 /* any weather defined */) {
  1568.                 EnableItem(menu, miViewWeather);
  1569.             } else {
  1570.                 DisableItem(menu, miViewWeather);
  1571.             }
  1572.             if (nummtypes > 0) {
  1573.                 EnableItem(menu, miViewMaterials);
  1574.                 /* (should do checkmark if anything in submenu is on) */
  1575.             } else {
  1576.                 DisableItem(menu, miViewMaterials);
  1577.             }
  1578.             if (world.daylength != 1) {
  1579.                 EnableItem(menu, miViewDaylight);
  1580.                 CheckItem(menu, miViewDaylight, frontmap->drawlighting);
  1581.             } else {
  1582.                 DisableItem(menu, miViewDaylight);
  1583.             }
  1584.             if (nummaps > 1) {
  1585.                 EnableItem(menu, miViewOtherMaps);
  1586.                 CheckItem(menu, miViewOtherMaps, frontmap->drawothermaps);
  1587.             } else {
  1588.                 DisableItem(menu, miViewOtherMaps);
  1589.             }
  1590.             if ((menu = GetMHandle(mViewWeather)) != nil) {
  1591.                 EnableItem(menu, 0);
  1592.                 if (temperatures_defined()) {
  1593.                     EnableItem(menu, miWeatherTemperature);
  1594.                     CheckItem(menu, miWeatherTemperature, frontmap->drawtemperature);
  1595.                 } else {
  1596.                     DisableItem(menu, miWeatherTemperature);
  1597.                 }
  1598.                 if (winds_defined()) {
  1599.                     EnableItem(menu, miWeatherWinds);
  1600.                     CheckItem(menu, miWeatherWinds, frontmap->drawwinds);
  1601.                 } else {
  1602.                     DisableItem(menu, miWeatherWinds);
  1603.                 }
  1604.                 if (clouds_defined()) {
  1605.                     EnableItem(menu, miWeatherClouds);
  1606.                     CheckItem(menu, miWeatherClouds, frontmap->drawclouds);
  1607.                 } else {
  1608.                     DisableItem(menu, miWeatherClouds);
  1609.                 }
  1610.                 /* should define what this means */
  1611.                 DisableItem(menu, miWeatherStorms);
  1612. /*                CheckItem(menu, miWeatherStorms, frontmap->drawstorms); */
  1613.             }
  1614.         }
  1615.     } else if (frontlist != NULL) {
  1616.         /* Do the list view menu similarly. */
  1617.         if ((menu = GetMHandle(mViewMap)) != nil) {
  1618.             DeleteMenu(mViewMap);
  1619.         }
  1620.         /* Make sure the menu is actually installed (is always at the end). */
  1621.         InsertMenu(listviewmenu, 0);
  1622.         if ((menu = GetMHandle(mViewList)) != nil) {
  1623.             EnableItem(menu, 0);
  1624.             if (1 /* at least one unit in list */) {
  1625.                 EnableItem(menu, miViewByType);
  1626.                 CheckItem(menu, miViewByType, (frontlist->mainsortmi == miViewByType));
  1627.                 EnableItem(menu, miViewByName);
  1628.                 CheckItem(menu, miViewByName, (frontlist->mainsortmi == miViewByName));
  1629.                 EnableItem(menu, miViewBySide);
  1630.                 CheckItem(menu, miViewBySide, (frontlist->mainsortmi == miViewBySide));
  1631.                 EnableItem(menu, miViewByActOrder);
  1632.                 CheckItem(menu, miViewByActOrder, (frontlist->mainsortmi == miViewByActOrder));
  1633.                 EnableItem(menu, miViewByLocation);
  1634.                 CheckItem(menu, miViewByLocation, (frontlist->mainsortmi == miViewByLocation));
  1635.                 /* should mark the secondary sort? */
  1636.                 EnableItem(menu, miViewWithTransport);
  1637.                 DisableItem(menu, miViewWithCommander);
  1638.                 EnableItem(menu, miViewIconSize);
  1639.                 CheckItem(menu, miViewIconSize, frontlist->largeicons);
  1640.             } else {
  1641.                 DisableItem(menu, miViewByType);
  1642.                 DisableItem(menu, miViewByName);
  1643.                 DisableItem(menu, miViewBySide);
  1644.                 DisableItem(menu, miViewByActOrder);
  1645.                 DisableItem(menu, miViewByLocation);
  1646.                 DisableItem(menu, miViewWithTransport);
  1647.                 DisableItem(menu, miViewWithCommander);
  1648.                 DisableItem(menu, miViewIconSize);
  1649.             }
  1650.         }
  1651.     } else {
  1652.         /* For any other window, disable any or all of the view menus, as needed. */
  1653.         if ((menu = GetMHandle(mViewList)) != nil) {
  1654.             DisableItem(menu, 0);
  1655.         }
  1656.         if ((menu = GetMHandle(mViewMap)) != nil) {
  1657.             DisableItem(menu, 0);
  1658.         }
  1659.     }
  1660.     if ((menu = GetMHandle(mMagnifications)) != nil) {
  1661.         /* Always on. */
  1662.         EnableItem(menu, 0);
  1663.         if (frontmap != NULL) {
  1664.             for (i = 0; i < NUMPOWERS; ++i) {
  1665.                 CheckItem(menu, i + 1, (i == frontmap->power));
  1666.             }
  1667.         }
  1668.     }
  1669.     if ((menu = GetMHandle(mMaterialTypes)) != nil) {
  1670.         /* Always on, if any material types defined. */
  1671.         if (nummtypes > 0) {
  1672.             EnableItem(menu, 0);
  1673.         } else {
  1674.             DisableItem(menu, 0);
  1675.         }
  1676.         if (frontmap != NULL) {
  1677.             for_all_material_types(m) {
  1678.                 if (any_cell_materials_defined() && cell_material_defined(m)) {
  1679.                     EnableItem(menu, m + 1);
  1680.                     CheckItem(menu, m + 1, frontmap->drawmaterials[m]);
  1681.                 } else {
  1682.                     DisableItem(menu, m + 1);
  1683.                 }
  1684.             }
  1685.         }
  1686.     }
  1687.     if ((menu = GetMHandle(mAITypes)) != nil) {
  1688.         /* Always on. */
  1689.         EnableItem(menu, 0);
  1690.         CheckItem(menu, 1, (!side_has_ai(dside)));
  1691.         CheckItem(menu, 2, (side_has_ai(dside)));
  1692.     }
  1693.     /* Everything has been tweaked, redraw the menu bar. */
  1694.     DrawMenuBar();
  1695. }
  1696.  
  1697. /* Tweak the command menu according to what the unit can do. */
  1698. /* (some of these should have the menu text tweaked also, terms weird sometimes) */
  1699.  
  1700. enable_commands_for_unit(menu, unit)
  1701. MenuHandle menu;
  1702. Unit *unit;
  1703. {
  1704.     int u = unit->type, u2;
  1705.  
  1706.     /* If we can select the unit at all, we can always get a closeup of it. */
  1707.     EnableItem(menu, miPlayCloseup);
  1708.     /* (how to do checkmarks if multiple units selected? use '-' as per HIG) */
  1709.     CheckItem(menu, miPlayCloseup, (find_unit_closeup(unit) != NULL));
  1710.     /* If we don't actually have any control over the unit, nothing more to do. */
  1711.     if (!side_controls_unit(dside, unit)) return;
  1712.     if (can_move_at_all(unit)) {
  1713.         EnableItem(menu, miPlayMove);
  1714.         EnableItem(menu, miPlayPatrol);
  1715.         /* also check for places to return to? */
  1716.         EnableItem(menu, miPlayReturn);
  1717.     }
  1718.     if (unit->plan) {
  1719.         EnableItem(menu, miPlayWake);
  1720.         CheckItem(menu, miPlayWake, !unit->plan->asleep);
  1721.         EnableItem(menu, miPlaySleep);
  1722.         CheckItem(menu, miPlaySleep, unit->plan->asleep);
  1723.         EnableItem(menu, miPlayDoneMoving);
  1724.         CheckItem(menu, miPlayDoneMoving, unit->plan->reserve);
  1725.     }
  1726.     if (can_create(unit) || can_complete(unit) /* or research? */) {
  1727.         EnableItem(menu, miPlayBuild);
  1728.     }
  1729.     if (can_repair(unit)) {
  1730.         EnableItem(menu, miPlayRepair);
  1731.     }
  1732.     if (can_attack(unit)) {
  1733.         EnableItem(menu, miPlayAttack);
  1734.     }
  1735.     if (can_attack(unit)) {
  1736.         EnableItem(menu, miPlayOverrun);
  1737.     }
  1738.     if (can_attack(unit)) {
  1739.         EnableItem(menu, miPlayFire);
  1740.     }
  1741.     if (can_detonate(unit)) {
  1742.         EnableItem(menu, miPlayDetonate);
  1743.     }
  1744.     if (1 /*dside->designer*/) {
  1745.         EnableItem(menu, miPlayGive);
  1746.     }
  1747.     if (can_disband_at_all(dside, unit)) {
  1748.         EnableItem(menu, miPlayDisband);
  1749.     }
  1750.     if (1 /* !unitnameslocked */) {
  1751.         EnableItem(menu, miPlayRename);
  1752.     }
  1753. }
  1754.  
  1755. /* Keyboard command handling. */
  1756.  
  1757. #ifdef PROFILING
  1758. extern int _trace;
  1759. #endif
  1760.  
  1761. typedef struct cmdtab {
  1762.     char fchar;                 /* character to match against */
  1763.     char ochar;                 /* 5.x character to match against */
  1764.     char *name;                 /* Full name of command */
  1765.     char *argtypes;
  1766.     int (*fn)();                /* pointer to command's function */
  1767.     char *help;                 /* short documentation string */
  1768. } CmdTab;
  1769.  
  1770. #define C(c) ((c)-0x40)
  1771.  
  1772. char tmpkey;
  1773.  
  1774. /* Start of alphabetized commands. */
  1775.  
  1776. int
  1777. do_add_player()
  1778. {
  1779.     SysBeep(20);
  1780. }
  1781.  
  1782. int
  1783. do_ai_side()
  1784. {
  1785.     SysBeep(20);
  1786. }
  1787.  
  1788. int
  1789. do_attack()
  1790. {
  1791.     do_attack_command();
  1792. }
  1793.  
  1794. int
  1795. do_auto()
  1796. {
  1797.     SysBeep(20);
  1798. }
  1799.  
  1800. int
  1801. do_build()
  1802. {
  1803.     do_construction_mi();
  1804. }
  1805.  
  1806. int
  1807. do_detonate()
  1808. {
  1809.     do_detonate_command();
  1810. }
  1811.  
  1812. char dirchars[] = "ulnbhy";
  1813.  
  1814. int tmpdir;
  1815.  
  1816. do_one_dir_move(unit)
  1817. Unit *unit;
  1818. {
  1819.     order_movedir(unit, tmpdir, 1);
  1820. }
  1821.  
  1822. int
  1823. do_dir()
  1824. {
  1825.     char *rawdir;
  1826.     Map *map;
  1827.  
  1828.     if ((map = map_from_window(FrontWindow())) != NULL
  1829.         && map->moveonclick) {
  1830.         rawdir = strchr(dirchars, tmpkey);
  1831.         if (!rawdir) {
  1832.             SysBeep(20);
  1833.             return;
  1834.         }
  1835.         tmpdir = rawdir - dirchars;
  1836.         apply_to_all_selected(do_one_dir_move);
  1837.     }
  1838. }
  1839.  
  1840. int
  1841. do_dir_multiple()
  1842. {
  1843. }
  1844.  
  1845. int
  1846. do_disband()
  1847. {
  1848.     SysBeep(20);
  1849. }
  1850.  
  1851. int
  1852. do_distance()
  1853. {
  1854.     SysBeep(20);
  1855. }
  1856.  
  1857. int
  1858. do_end_turn()
  1859. {
  1860.     /* Special-case this, depending on which window was in front. */
  1861.     if (FrontWindow() == constructionwin) {
  1862.         Point pt;
  1863.         extern ControlHandle constructbutton;
  1864.         
  1865.         pt.h = (*constructbutton)->contrlRect.left + 8;
  1866.         pt.v = (*constructbutton)->contrlRect.top + 8;
  1867.         do_mouse_down_construction(pt, 0);
  1868.     } else {
  1869.         finish_turn(dside);
  1870.     }
  1871. }
  1872.  
  1873. int
  1874. do_fire()
  1875. {
  1876.     do_fire_command();
  1877. }
  1878.  
  1879. int
  1880. do_give()
  1881. {
  1882.     SysBeep(20);
  1883. }
  1884.  
  1885. int
  1886. do_give_unit()
  1887. {
  1888.     SysBeep(20);
  1889. }
  1890.  
  1891. int doingother = FALSE;
  1892.  
  1893. int
  1894. do_help()
  1895. {
  1896.     help_dialog();
  1897. }
  1898.  
  1899. int
  1900. do_message()
  1901. {
  1902.     SysBeep(20);
  1903. }
  1904.  
  1905. int
  1906. do_move_to()
  1907. {
  1908.     SysBeep(20);
  1909. }
  1910.  
  1911. int
  1912. do_name()
  1913. {
  1914.     SysBeep(20);
  1915. }
  1916.  
  1917. int
  1918. do_other()
  1919. {
  1920.     /* Don't allow recursion with this command. */
  1921.     if (!doingother) {
  1922.         doingother = TRUE;
  1923.         command_dialog();
  1924.         doingother = FALSE;
  1925.     } else {
  1926.         SysBeep(20);
  1927.     }
  1928. }
  1929.  
  1930. command_dialog()
  1931. {
  1932.     short done = FALSE, ditem;
  1933.     char *cmd = NULL;
  1934.     Str255 tmpstr;
  1935.     DialogPtr win;
  1936.     short itemtype;  Handle itemhandle;  Rect itemrect;
  1937.  
  1938.     win = GetNewDialog(dCommand, NULL, (DialogPtr) -1L);
  1939.     ShowWindow(win);
  1940.     while (!done) {
  1941.         draw_default_button(win, diCommandOK);
  1942.         ModalDialog(NULL, &ditem);
  1943.         switch (ditem) {
  1944.             case diCommandOK:
  1945.                 GetDItem(win, diCommandText, &itemtype, &itemhandle, &itemrect);
  1946.                 cmd = get_string_from_item(itemhandle);
  1947.                 /* Fall into next case. */
  1948.             case diCommandCancel:
  1949.                 done = TRUE;
  1950.                 break;
  1951.         }
  1952.     }
  1953.     DisposDialog(win);
  1954.     if (cmd != NULL) {
  1955.         execute_named_command(cmd);
  1956.     }
  1957. }
  1958.  
  1959. int
  1960. do_produce()
  1961. {
  1962.     SysBeep(20);
  1963. }
  1964.  
  1965. int
  1966. do_quit()
  1967. {
  1968.     quit_the_game();
  1969. }
  1970.  
  1971. int
  1972. do_recenter()
  1973. {
  1974.     SysBeep(20);
  1975. }
  1976.  
  1977. int
  1978. do_refresh()
  1979. {
  1980.     Map *map;
  1981.     List *list;
  1982.  
  1983.     reset_coverage();
  1984.     reset_all_views();
  1985.     /* (should just iterate through raw windows) */
  1986.     for_all_maps(map) {
  1987.         force_update(map->window);
  1988.     }
  1989.     for_all_lists(list) {
  1990.         force_update(list->window);
  1991.     }
  1992.     if (gamewin != nil) {
  1993.         force_update(gamewin);
  1994.     }
  1995.     if (historywin != nil) {
  1996.         force_update(historywin);
  1997.     }
  1998.     if (constructionwin != nil) {
  1999.         force_update(constructionwin);
  2000.     }
  2001.     if (helpwin != nil) {
  2002.         force_update(helpwin);
  2003.     }
  2004. }
  2005.  
  2006. int
  2007. do_reserve()
  2008. {
  2009.     do_reserve_command(TRUE);
  2010. }
  2011.  
  2012. int
  2013. do_return()
  2014. {
  2015.     do_return_mi();
  2016. }
  2017.  
  2018. int
  2019. do_sleep()
  2020. {
  2021.     SysBeep(20);
  2022. }
  2023.  
  2024. int 
  2025. do_survey()
  2026. {
  2027.     Map *map;
  2028.  
  2029.     if ((map = map_from_window(FrontWindow())) != NULL) {
  2030.         toggle_survey(map);
  2031.     }
  2032. }
  2033.  
  2034. int
  2035. do_take()
  2036. {
  2037.     SysBeep(20);
  2038. }
  2039.  
  2040. int
  2041. do_take_unit()
  2042. {
  2043.     SysBeep(20);
  2044. }
  2045.  
  2046. int
  2047. do_version()
  2048. {
  2049.     do_about_box();
  2050. }
  2051.  
  2052. int
  2053. do_wake()
  2054. {
  2055.     do_sleep_command(FALSE, FALSE);
  2056.     do_reserve_command(FALSE, FALSE);
  2057. }
  2058.  
  2059. int
  2060. do_wake_all()
  2061. {
  2062.     do_sleep_command(FALSE, TRUE);
  2063.     do_reserve_command(FALSE, TRUE);
  2064. }
  2065.  
  2066. #ifdef DESIGNERS
  2067.  
  2068. int
  2069. do_design()
  2070. {
  2071.     SysBeep(20);
  2072. }
  2073.  
  2074. #endif
  2075.  
  2076. #ifdef DEBUGGING
  2077.  
  2078. int
  2079. do_debug()
  2080. {
  2081.     SysBeep(20);
  2082. }
  2083.  
  2084. int
  2085. do_debugg()
  2086. {
  2087.     SysBeep(20);
  2088. }
  2089.  
  2090. int
  2091. do_debugm()
  2092. {
  2093.     SysBeep(20);
  2094. }
  2095.  
  2096.  
  2097. #endif
  2098.  
  2099. /* End of alphabetized commands. */
  2100.  
  2101. CmdTab commands[] = {
  2102.  
  2103. #undef DEF_CMD
  2104. #define DEF_CMD(LETTER,OLDLETTER,NAME,ARGS,FN,HELP) { LETTER, OLDLETTER, NAME, ARGS, FN, HELP},
  2105.  
  2106. #include "cmd.def"
  2107.  
  2108.   { 0, 0, NULL, NULL, NULL, NULL }
  2109. };
  2110.  
  2111. do_keyboard_command(key)
  2112. char key;
  2113. {
  2114.     CmdTab *cmd;
  2115.     int (*fn)();
  2116.  
  2117.     DGprintf("Typed '%c' (0x%x)\n", key, key);
  2118.     switch (key) {
  2119.         case 'd':  do_find_next_mi();  break;
  2120.         case 's':  do_sleep_command(TRUE, FALSE);  break;
  2121.         case 'c':  do_ai_control_command();  break;
  2122.         case 'C':  do_clear_plan_command();  break;
  2123.         case '*':  force_global_replan(dside);  break;
  2124.         case '\033': modaltool = 0;  break;
  2125. #ifdef DEBUGGING
  2126.         case 'D':  toggle_debugging(&Debug);  break;
  2127.         case 'M':  toggle_debugging(&DebugM); break;
  2128.         case 'G':  toggle_debugging(&DebugG); break;
  2129. /*        case 'P':  toggle_debugging(&Profile); break; */
  2130.         case 'T':
  2131.             toggle_debugging(&Profile);
  2132. #ifdef PROFILING
  2133.             _trace = 1;
  2134. #endif
  2135.             break;
  2136. #endif /* DEBUGGING */
  2137.         default:
  2138.             /* Look through the generic command table. */
  2139.             for (cmd = commands; cmd->name != NULL; ++cmd) {
  2140.                 if (key == cmd->fchar) {
  2141.                     if ((fn = cmd->fn) == NULL) {
  2142.                         run_warning("no command function for %s (0x%x)?", cmd->name, key);
  2143.                         return;
  2144.                     }
  2145.                     tmpkey = key;
  2146.                     (*fn)();
  2147.                     return;
  2148.                 }
  2149.             }
  2150.             /* Silently ignore unrecognized chars? */
  2151.             break;
  2152.     }
  2153. }
  2154.  
  2155. execute_named_command(cmdstr)
  2156. char *cmdstr;
  2157. {
  2158.     CmdTab *cmd;
  2159.     int (*fn)();
  2160.  
  2161.     for (cmd = commands; cmd->name != NULL; ++cmd) {
  2162.         if (strcmp(cmdstr, cmd->name) == 0) {
  2163.             if ((fn = cmd->fn) == NULL) {
  2164.                 run_warning("no command function for %s?", cmd->name);
  2165.                 return;
  2166.             }
  2167.             tmpkey = '\0';
  2168.             (*fn)();
  2169.             return;
  2170.         }
  2171.     }
  2172.     SysBeep(20);
  2173. }
  2174.  
  2175. #ifdef DEBUGGING
  2176.  
  2177. /* Junk associated with debug output. */
  2178.  
  2179. /* This is all fairly elaborate because we need to be able to collect
  2180.    detailed logs of AI activity over different periods of time, and just
  2181.    dumping to stdout doesn't work in a window system. */
  2182.  
  2183. #ifdef USE_CONSOLE
  2184. #ifdef THINK_C
  2185. #include <console.h>
  2186. #endif
  2187. #endif
  2188.  
  2189. extern FILE *pfp;
  2190.  
  2191. FILE *ffp = NULL;
  2192.  
  2193. int firstdebug = TRUE;
  2194.  
  2195. update_debugging()
  2196. {
  2197.     if (Debug || DebugG || DebugM || Profile) {
  2198.         /* Always close the file if open, forces to desirable state. */
  2199.         if (ffp != NULL) {
  2200.             fclose(ffp);
  2201.             ffp = NULL;
  2202.         }
  2203.         /* Reopen the file. */
  2204.         if (ffp == NULL) {
  2205.             ffp = fopen("Xconq.DebugOut", "a");
  2206.         }
  2207.         if (ffp != NULL) {
  2208.             if (Debug) dfp = ffp;
  2209.             if (DebugG) dgfp = ffp;
  2210.             if (DebugM) dmfp = ffp;
  2211.             if (Profile) pfp = ffp;
  2212.         }
  2213.     }
  2214. }
  2215.  
  2216. /* Debug output goes to a file. */
  2217.  
  2218. toggle_debugging(flagp)
  2219. int *flagp;
  2220. {
  2221. #ifdef PROFILING
  2222.     extern int _profile;
  2223. #endif
  2224.  
  2225.     /* Always close the file if open, forces to desirable state. */
  2226.     if (ffp != NULL) {
  2227.         fclose(ffp);
  2228.         ffp = NULL;
  2229.     }
  2230.     /* Flip the state of the debugging flag, if supplied. */ 
  2231.     if (flagp != NULL) {
  2232.         *flagp = ! *flagp;
  2233.     }
  2234.     /* (Re-)open the debugging transcript file. */
  2235.     if (ffp == NULL) {
  2236.         ffp = fopen("Xconq.DebugOut", (firstdebug ? "w" : "a"));
  2237.         firstdebug = FALSE;
  2238.     }
  2239.     if (flagp != NULL) {
  2240.         /* Indicate which flags are now on. */
  2241.         fprintf(ffp, "\n\n*********** %s %s %s %s **********\n\n",
  2242.                 (Debug ? "Debug" : ""), (DebugM ? "DebugM" : ""),
  2243.                 (DebugG ? "DebugG" : ""), (Profile ? "Profile" : ""));
  2244.         /* Indicate this in a window also. */
  2245.         draw_game();
  2246.     }
  2247.     /* Set specific debug file pointers to be the same as the
  2248.        pointer to the file. */
  2249.     if (ffp != NULL) {
  2250.         if (Debug) dfp = ffp;
  2251.         if (DebugG) dgfp = ffp;
  2252.         if (DebugM) dmfp = ffp;
  2253.         if (Profile) pfp = ffp;
  2254.     }
  2255. #ifdef PROFILING
  2256. #ifdef THINK_C
  2257.     if (Profile && !_profile) {
  2258.         InitProfile(1000, 100);
  2259.     }
  2260.     if (!Profile && _profile) {
  2261.         EndProfile();
  2262.     }
  2263. #endif
  2264. #endif
  2265.     /* If all debugging flags have been turned off, close the file too. */
  2266.     if (!Debug && !DebugG && !DebugM && !Profile) {
  2267.         if (ffp != NULL) {
  2268.             fclose(ffp);
  2269.             ffp = NULL;
  2270.         }
  2271.     }
  2272. }
  2273.  
  2274. #endif /* DEBUGGING */
  2275.